// utils/media.js
const app = getApp()

/**
 * 图片选择选项
 * @typedef {Object} ImageSelectOptions
 * @property {number} [count]
 * @property {string[]} [sizeType]
 * @property {string[]} [sourceType]
 * @property {function} [success]
 * @property {function} [fail]
 */

/**
 * 音频录制选项
 * @typedef {Object} AudioRecordOptions
 * @property {number} [duration]
 * @property {number} [sampleRate]
 * @property {number} [numberOfChannels]
 * @property {number} [encodeBitRate]
 * @property {string} [format]
 * @property {number} [frameSize]
 */

// 语音播放管理器
class AudioManager {
  static instance
  currentAudio = null
  constructor() {
    this.currentAudioId = ''
    this.playingCallback = null
  }

  static getInstance() {
    if (!AudioManager.instance) {
      AudioManager.instance = new AudioManager()
    }
    return AudioManager.instance
  }

  // 设置播放状态回调
  setPlayingCallback(callback) {
    this.playingCallback = callback
  }

  // 播放语音
  play(audioId, audioUrl) {
    return new Promise((resolve, reject) => {
      try {
        // 如果正在播放其他音频，先停止
        if (this.currentAudio && this.currentAudioId !== audioId) {
          this.stop()
        }

        // 如果是同一个音频，切换播放状态
        if (this.currentAudioId === audioId && this.currentAudio) {
          if (this.currentAudio.paused) {
            this.currentAudio.play()
            this.notifyPlayingState(audioId, true)
          } else {
            this.currentAudio.pause()
            this.notifyPlayingState(audioId, false)
          }
          resolve()
          return
        }

        // 创建新的音频实例
        this.currentAudio = wx.createInnerAudioContext()
        this.currentAudioId = audioId
        this.currentAudio.src = audioUrl

        // 监听事件
        this.currentAudio.onPlay(() => {
          this.notifyPlayingState(audioId, true)
          resolve()
        })

        this.currentAudio.onPause(() => {
          this.notifyPlayingState(audioId, false)
        })

        this.currentAudio.onEnded(() => {
          this.notifyPlayingState(audioId, false)
          this.cleanup()
        })

        this.currentAudio.onError((err) => {
          console.error('音频播放失败:', err)
          this.notifyPlayingState(audioId, false)
          this.cleanup()
          reject(err)
        })

        // 开始播放
        this.currentAudio.play()
      } catch (error) {
        console.error('播放音频失败:', error)
        reject(error)
      }
    })
  }

  // 暂停播放
  pause() {
    if (this.currentAudio && !this.currentAudio.paused) {
      this.currentAudio.pause()
      this.notifyPlayingState(this.currentAudioId, false)
    }
  }

  // 停止播放
  stop() {
    if (this.currentAudio) {
      this.currentAudio.stop()
      this.notifyPlayingState(this.currentAudioId, false)
      this.cleanup()
    }
  }

  // 获取当前播放的音频ID
  getCurrentAudioId() {
    return this.currentAudioId
  }

  // 检查是否正在播放
  isPlaying(audioId) {
    if (audioId && audioId !== this.currentAudioId) {
      return false
    }
    return this.currentAudio ? !this.currentAudio.paused : false
  }

  // 清理资源
  cleanup() {
    if (this.currentAudio) {
      this.currentAudio.destroy()
      this.currentAudio = null
    }
    this.currentAudioId = ''
  }

  // 通知播放状态变化
  notifyPlayingState(audioId, isPlaying) {
    if (this.playingCallback) {
      this.playingCallback(audioId, isPlaying)
    }
  }

  // 销毁管理器
  destroy() {
    this.stop()
    this.playingCallback = null
  }
}

// 语音录制管理器
class RecorderManager {
  static instance
  recorder = null
  constructor() {
    this.isRecording = false
    this.recordingCallback = null
  }

  static getInstance() {
    if (!RecorderManager.instance) {
      RecorderManager.instance = new RecorderManager()
    }
    return RecorderManager.instance
  }

  constructor() {
    this.recorder = wx.getRecorderManager()
    this.setupRecorderEvents()
  }

  // 设置录制状态回调
  setRecordingCallback(callback) {
    this.recordingCallback = callback
  }

  // 开始录制
  startRecord(options = {}) {
    return new Promise((resolve, reject) => {
      if (this.isRecording) {
        reject(new Error('正在录制中'))
        return
      }

      const defaultOptions = {
        duration: 60000, // 最长60秒
        sampleRate: 16000,
        numberOfChannels: 1,
        encodeBitRate: 96000,
        format: 'mp3',
        frameSize: 50
      }

      const recordOptions = { ...defaultOptions, ...options }

      try {
        this.recorder?.start(recordOptions)
        this.isRecording = true
        this.notifyRecordingState(true)
        resolve()
      } catch (error) {
        console.error('开始录制失败:', error)
        reject(error)
      }
    })
  }

  // 停止录制
  stopRecord() {
    return new Promise((resolve, reject) => {
      if (!this.isRecording) {
        reject(new Error('未在录制中'))
        return
      }

      // 设置一次性监听器
      const onStop = (res) => {
        this.isRecording = false
        this.notifyRecordingState(false)
        resolve(res.tempFilePath)
        this.recorder?.offStop(onStop)
      }

      const onError = (err) => {
        this.isRecording = false
        this.notifyRecordingState(false)
        reject(err)
        this.recorder?.offError(onError)
      }

      this.recorder?.onStop(onStop)
      this.recorder?.onError(onError)
      this.recorder?.stop()
    })
  }

  // 暂停录制
  pauseRecord() {
    if (this.isRecording) {
      this.recorder?.pause()
    }
  }

  // 恢复录制
  resumeRecord() {
    if (this.isRecording) {
      this.recorder?.resume()
    }
  }

  // 检查是否正在录制
  getIsRecording() {
    return this.isRecording
  }

  // 设置录制器事件
  setupRecorderEvents() {
    if (!this.recorder) return

    this.recorder.onStart(() => {
      console.log('录制开始')
    })

    this.recorder.onPause(() => {
      console.log('录制暂停')
    })

    this.recorder.onResume(() => {
      console.log('录制恢复')
    })

    this.recorder.onFrameRecorded((res) => {
      // 可以在这里处理录制帧数据
      if (this.recordingCallback) {
        this.recordingCallback(true, res.frameBuffer ? res.frameBuffer.byteLength : 0)
      }
    })

    this.recorder.onError((err) => {
      console.error('录制错误:', err)
      this.isRecording = false
      this.notifyRecordingState(false)
    })
  }

  // 通知录制状态变化
  notifyRecordingState(isRecording, duration) {
    if (this.recordingCallback) {
      this.recordingCallback(isRecording, duration)
    }
  }
}

// 媒体工具类
class MediaUtils {
  static audioManager = AudioManager.getInstance()
  static recorderManager = RecorderManager.getInstance()

  // 选择图片
  static selectImages(options = {}) {
    return new Promise((resolve, reject) => {
      const defaultOptions = {
        count: 9,
        sizeType: ['original', 'compressed'],
        sourceType: ['album', 'camera']
      }

      const selectOptions = { ...defaultOptions, ...options }

      wx.chooseMedia({
        count: selectOptions.count,
        mediaType: ['image'],
        sourceType: selectOptions.sourceType,
        maxDuration: 30,
        camera: 'back',
        success: (res) => {
          const tempFilePaths = res.tempFiles.map(file => file.tempFilePath)
          resolve(tempFilePaths)
          if (options.success) {
            options.success(res)
          }
        },
        fail: (err) => {
          console.error('选择图片失败:', err)
          reject(err)
          if (options.fail) {
            options.fail(err)
          }
        }
      })
    })
  }

  // 预览图片
  static previewImages(urls, current = '') {
    wx.previewImage({
      urls,
      current: current || urls[0]
    })
  }

  // 保存图片到相册
  static saveImageToPhotosAlbum(filePath) {
    return new Promise((resolve, reject) => {
      wx.saveImageToPhotosAlbum({
        filePath,
        success: () => {
          app.showSuccess('保存成功')
          resolve()
        },
        fail: (err) => {
          console.error('保存图片失败:', err)
          if (err.errMsg.includes('auth deny')) {
            wx.showModal({
              title: '提示',
              content: '需要授权访问相册才能保存图片',
              success: (res) => {
                if (res.confirm) {
                  wx.openSetting()
                }
              }
            })
          } else {
            app.showError('保存失败')
          }
          reject(err)
        }
      })
    })
  }

  // 上传图片
  static uploadImages(filePaths) {
    return Promise.all(
      filePaths.map(filePath => MediaUtils.uploadSingleImage(filePath))
    )
  }

  // 上传单张图片
  static uploadSingleImage(filePath) {
    return new Promise((resolve, reject) => {
      wx.uploadFile({
        url: `${app.globalData.baseUrl}/api/upload/image`,
        filePath,
        name: 'file',
        header: {
          'Authorization': `Bearer ${app.globalData.token}`
        },
        success: (res) => {
          try {
            const data = JSON.parse(res.data)
            if (data.code === 200) {
              resolve(data.data.url)
            } else {
              reject(new Error(data.message || '上传失败'))
            }
          } catch (e) {
            reject(new Error('解析响应失败'))
          }
        },
        fail: reject
      })
    })
  }

  // 开始录音
  static startRecord(options = {}) {
    return MediaUtils.recorderManager.startRecord(options)
  }

  // 停止录音
  static stopRecord() {
    return MediaUtils.recorderManager.stopRecord()
  }

  // 播放语音
  static playAudio(audioId, audioUrl) {
    return MediaUtils.audioManager.play(audioId, audioUrl)
  }

  // 暂停播放
  static pauseAudio() {
    MediaUtils.audioManager.pause()
  }

  // 停止播放
  static stopAudio() {
    MediaUtils.audioManager.stop()
  }

  // 检查是否正在播放
  static isAudioPlaying(audioId) {
    return MediaUtils.audioManager.isPlaying(audioId)
  }

  // 检查是否正在录制
  static isRecording() {
    return MediaUtils.recorderManager.getIsRecording()
  }

  // 设置音频播放状态回调
  static setAudioPlayingCallback(callback) {
    MediaUtils.audioManager.setPlayingCallback(callback)
  }

  // 设置录音状态回调
  static setRecordingCallback(callback) {
    MediaUtils.recorderManager.setRecordingCallback(callback)
  }

  // 上传语音文件
  static uploadAudio(filePath) {
    return new Promise((resolve, reject) => {
      wx.uploadFile({
        url: `${app.globalData.baseUrl}/api/upload/audio`,
        filePath,
        name: 'file',
        header: {
          'Authorization': `Bearer ${app.globalData.token}`
        },
        success: (res) => {
          try {
            const data = JSON.parse(res.data)
            if (data.code === 200) {
              resolve(data.data.url)
            } else {
              reject(new Error(data.message || '上传失败'))
            }
          } catch (e) {
            reject(new Error('解析响应失败'))
          }
        },
        fail: reject
      })
    })
  }

  // 获取文件信息
  static getFileInfo(filePath) {
    return new Promise((resolve, reject) => {
      wx.getFileInfo({
        filePath,
        success: resolve,
        fail: reject
      })
    })
  }

  // 格式化文件大小
  static formatFileSize(bytes) {
    if (bytes === 0) return '0 B'
    
    const k = 1024
    const sizes = ['B', 'KB', 'MB', 'GB']
    const i = Math.floor(Math.log(bytes) / Math.log(k))
    
    return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
  }

  // 格式化音频时长
  static formatAudioDuration(seconds) {
    const minutes = Math.floor(seconds / 60)
    const remainingSeconds = Math.floor(seconds % 60)
    return `${minutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`
  }

  // 清理资源
  static cleanup() {
    MediaUtils.audioManager.destroy()
  }
}

// 导出单例实例
const audioManager = AudioManager.getInstance()
const recorderManager = RecorderManager.getInstance()

module.exports = {
  MediaUtils,
  audioManager,
  recorderManager
}